package com.ruan.service.impl;

import com.anji.captcha.model.common.ResponseModel;
import com.anji.captcha.model.vo.CaptchaVO;
import com.anji.captcha.service.CaptchaService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruan.dto.LoginDto;
import com.ruan.entity.LoginUser;
import com.ruan.entity.Order;
import com.ruan.entity.R;
import com.ruan.entity.User;
import com.ruan.mapper.OrderMapper;
import com.ruan.service.UserService;
import com.ruan.mapper.UserMapper;
import com.ruan.utils.Auth0JwtUtils;
import com.ruan.utils.LongAuth0JwtUtils;
import com.ruan.utils.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.MessageBuilder;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicReference;

/**
* @author 59499
* @description 针对表【tb_user】的数据库操作Service实现
* @createDate 2023-09-21 20:28:08
*/
@Slf4j
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User>
    implements UserService{

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private CaptchaService captchaService;

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private OrderMapper orderMapper;

    @Override
    public R<Void> register(User user) {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("username",user.getUsername());
        User user1 = userMapper.selectOne(queryWrapper);
        if(user1!=null){
            return R.error("用户名已存在");
        }
        QueryWrapper<User> queryWrapper1 = new QueryWrapper<>();
        queryWrapper1.eq("nickname",user.getNickname());
        User user2 = userMapper.selectOne(queryWrapper1);
        if(user2!=null){
            return R.error("该昵称已存在");
        }
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        String encodedPassword = passwordEncoder.encode(user.getPassword());
        user.setPassword(encodedPassword);
        boolean save = save(user);
        if(!save){
            return R.error("注册异常");
        }
        int row = userMapper.saveRole(user.getId());
        if(row != 1){
            return R.error("注册异常");
        }
        //用户名就是邮箱
        //注册的时候就激活邮箱
        AtomicReference<String> errorMessage = new AtomicReference<>();
        String message = user.getUsername();
        rabbitTemplate.send("email-exchange", "email-routing-key", MessageBuilder.withBody(message.getBytes())
                .setContentType(MessageProperties.CONTENT_TYPE_TEXT_PLAIN)
                .build(), new CorrelationData(UUID.randomUUID().toString()));

        rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
            if (ack) {
                log.info("邮件消息发送成功");
                // 发送成功后的逻辑处理
            } else {
                log.error("邮件发送失败");
                errorMessage.set("邮件发送失败");
            }
        });
        if (errorMessage.get() != null && !errorMessage.get().isEmpty()) {
            return R.error(String.valueOf(errorMessage));
        }
        return R.ok("注册成功");
    }


    @Override
    public R<Void> activation(String token) {
        if(!StringUtils.hasText(token)){
            return  R.error("token为空");
        }
        boolean b = Auth0JwtUtils.isExpired(token);
        if(b){
            return R.error("token超时");
        }
        String username="";
        try {
            username = Auth0JwtUtils.getClaims(token).get("username").asString();
        } catch (Exception e) {
            // 返回状态码给前端
            return R.error("token无效");
        }
        if(!StringUtils.hasText(username)){
            return R.error("token中的username为空");
        }
        QueryWrapper<User> queryWrapper =new QueryWrapper<>();
        queryWrapper.eq("username",username);
        Integer activation = getOne(queryWrapper).getActivation();
        if(activation==1){
            return R.error("邮箱已激活");
        }

        //更新激活状态
        User user=new User();
        user.setActivation(1);
        UpdateWrapper<User> updateWrapper =new UpdateWrapper<>();
        updateWrapper.eq("username",username);
        boolean update = update(user, updateWrapper);
        if(!update){
            return R.error("激活失败");
        }
        return R.ok("激活成功");
    }

    @Override
    public R<Map<String, String>> login(LoginDto loginDto) {
        //自带的 CaptchaVO
        CaptchaVO captchaVO = new CaptchaVO();
        //获取二次验证
        captchaVO.setCaptchaVerification(loginDto.getCaptchaVerification());
        ResponseModel response = captchaService.verification(captchaVO);

        //滑块验证通过
        if(response.isSuccess()){
            UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginDto.getUsername(), loginDto.getPassword());
            Authentication authenticate = authenticationManager.authenticate(authenticationToken);
            if (Objects.isNull(authenticate)) {
                return new R<>(100, "用户名或密码错误");
            }
            //使用userid生成token
            LoginUser loginUser = (LoginUser) authenticate.getPrincipal();
            Integer userId = loginUser.getUser().getId();
            HashMap<String, Object> userMap = new HashMap<>();
            userMap.put("userId", userId.toString());
            String token = Auth0JwtUtils.sign(userMap);
            String longToken = LongAuth0JwtUtils.sign(userMap);
            loginUser.setToken(token);
            loginUser.setLongToken(longToken);
            //authenticate存入redis
            RedisUtil.set("login:" + userId, loginUser);
            //把token响应给前端
            HashMap<String, String> map = new HashMap<>();
            map.put("token", token);
            map.put("id", String.valueOf(loginUser.getUser().getId()));
            map.put("userType", String.valueOf(loginUser.getUser().getUserType()));
            map.put("username", loginUser.getUser().getUsername());
            map.put("nickname", loginUser.getUser().getNickname());
            map.put("userId", String.valueOf(loginUser.getUser().getId()));
            return R.ok("登陆成功", map);
        }
        return R.error("验证失败");
    }

    @Override
    public R<Void> logout() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
        Integer userid = loginUser.getUser().getId();
        RedisUtil.del("login:"+userid);
        return R.ok("退出成功");
    }

    @Override
    public R<User> getOrderOwnData(Integer orderId) {
        QueryWrapper<Order> orderQueryWrapper = new QueryWrapper<>();
        orderQueryWrapper.select("own_name");
        orderQueryWrapper.eq("order_id",orderId);
        Order order = orderMapper.selectOne(orderQueryWrapper);
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.eq("nickname",order.getOwnName());
        userQueryWrapper.eq("state",1);
        userQueryWrapper.select("username","nickname","update_time");
        User user = userMapper.selectOne(userQueryWrapper);
        return R.ok("获取成功",user);
    }
}




